package com.flbill.exception;

import com.flbill.common.constant.MessageConstant;
import com.flbill.common.exception.*;
import com.flbill.common.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.validation.BindException;
import java.sql.SQLIntegrityConstraintViolationException;
import jakarta.validation.ConstraintViolationException;

/**
 * 全局异常处理器，处理项目中抛出的业务异常
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    // 账号不存在
    @ExceptionHandler(AccountNotFoundException.class)
    public Result<?> handleAccountNotFound(AccountNotFoundException ex) {
        log.warn("账号不存在: {}", ex.getMessage());
        return Result.error(404, MessageConstant.ACCOUNT_NOT_FOUND);
    }

    // 密码错误
    @ExceptionHandler(PasswordErrorException.class)
    public Result<?> handlePasswordError(PasswordErrorException ex) {
        log.warn("密码错误: {}", ex.getMessage());
        return Result.error(401, MessageConstant.PASSWORD_ERROR);
    }

    // 账号被锁定
    @ExceptionHandler(AccountLockedException.class)
    public Result<?> handleAccountLocked(AccountLockedException ex) {
        log.warn("账号被锁定: {}", ex.getMessage());
        return Result.error(403, MessageConstant.ACCOUNT_LOCKED);
    }

    // 登录失败
    @ExceptionHandler(LoginFailedException.class)
    public Result<?> handleLoginFailed(LoginFailedException ex) {
        log.warn("登录失败: {}", ex.getMessage());
        return Result.error(401, MessageConstant.LOGIN_FAILED);
    }

    // 未登录
    @ExceptionHandler(UserNotLoginException.class)
    public Result<?> handleUserNotLogin(UserNotLoginException ex) {
        log.warn("用户未登录: {}", ex.getMessage());
        return Result.error(401, MessageConstant.USER_NOT_LOGIN);
    }

    // 密码修改失败
    @ExceptionHandler(PasswordEditFailedException.class)
    public Result<?> handlePasswordEditFailed(PasswordEditFailedException ex) {
        log.warn("密码修改失败: {}", ex.getMessage());
        return Result.error(400, MessageConstant.PASSWORD_EDIT_FAILED);
    }

    // 业务通用异常
    @ExceptionHandler(BaseException.class)
    public Result<?> handleBaseException(BaseException ex) {
        log.warn("业务异常: {}", ex.getMessage());
        return Result.error(400, ex.getMessage());
    }

    // 订单、购物车、地址本等业务异常
    @ExceptionHandler({
            OrderBusinessException.class,
            ShoppingCartBusinessException.class,
            AddressBookBusinessException.class,
            DeletionNotAllowedException.class,
            SetmealEnableFailedException.class
    })
    public Result<?> handleBusinessExceptions(BaseException ex) {
        log.warn("业务异常: {}", ex.getMessage());
        return Result.error(400, ex.getMessage());
    }

    // SQL唯一约束异常
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public Result<?> handleSQLIntegrity(SQLIntegrityConstraintViolationException ex) {
        String message = ex.getMessage();
        log.warn("数据库唯一约束异常: {}", message);
        if (message != null && message.contains("Duplicate entry")) {
            String[] split = message.split("'");
            String username = split.length > 1 ? split[1] : "";
            String msg = "用户名" + username + "已存在";
            return Result.error(409, msg);
        } else {
            return Result.error(500, MessageConstant.UNKNOWN_ERROR);
        }
    }

    // 参数校验异常（@Valid/@Validated）
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<?> handleMethodArgumentNotValid(MethodArgumentNotValidException ex) {
        StringBuilder sb = new StringBuilder();
        ex.getBindingResult().getFieldErrors().forEach(error ->
                sb.append(error.getField()).append(": ").append(error.getDefaultMessage()).append("; "));
        log.warn("参数校验异常: {}", sb);
        return Result.error(400, sb.toString());
    }

    // 参数绑定异常
    @ExceptionHandler(BindException.class)
    public Result<?> handleBindException(BindException ex) {
        StringBuilder sb = new StringBuilder();
        ex.getBindingResult().getFieldErrors().forEach(error ->
                sb.append(error.getField()).append(": ").append(error.getDefaultMessage()).append("; "));
        log.warn("参数绑定异常: {}", sb);
        return Result.error(400, sb.toString());
    }

    // 单个参数校验异常
    @ExceptionHandler(ConstraintViolationException.class)
    public Result<?> handleConstraintViolation(ConstraintViolationException ex) {
        log.warn("参数校验异常: {}", ex.getMessage());
        return Result.error(400, ex.getMessage());
    }

    // 兜底异常
    @ExceptionHandler(Exception.class)
    public Result<?> handleGlobalException(Exception ex) {
        log.error("全局异常：", ex);
        return Result.error(500, "服务器异常，请稍后再试");
    }
}
